package com.jb.framework;

import com.jb.framework.database.DatabaseManager;
import com.jb.framework.database.Predicate;
import com.jb.framework.util.BeanUtil;
import com.jb.util.ClassUtil;
import com.jb.web.application.configuration.Config;

import com.jb.web.model.ChangeListener;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class PersistentManagerRegistry {
    static private Log log = LogFactory.getLog(ModelBean.class.getName());
    public static String pClassName;
    static HashMap persistentManagers = new HashMap();
    static HashMap persistentDescriptors = new HashMap();
    static List changeListeners = new ArrayList();

    public static PersistentDescriptor getPersistentDescriptor(Class clazz) {
        PersistentDescriptor pp = (PersistentDescriptor) persistentDescriptors.get(clazz);

        if (pp != null) {
            return pp;
        } else if (clazz.getSuperclass() == Object.class) {
            return null;
        } else {
            return getPersistentDescriptor(clazz.getSuperclass());
        }
    }

    public static PersistentManager getPersistentManager(Class clazz) {
        PersistentManager s = (PersistentManager) persistentManagers.get(clazz);
        if (s == null) {
            //default
            String pmName = Config.getInstance().getPersistentManagerName();
            s = (PersistentManager) ClassUtil.createInstance(pmName);
            if(s instanceof DatabaseManager)
                ((DatabaseManager)s).registerDescriptor(clazz, getPersistentDescriptor(clazz));
            registerPersistentManager(clazz, s);
        } 
        return s;
    }

    public static void addChangeListener(ChangeListener listener) {
        changeListeners.add(listener);
    }

    public static void create(PersistentContext ctx, Object obj) {
        if (obj instanceof ModelBean) {
            ((ModelBean) obj).create(ctx);
        }
    }

    public static void delete(Class classToDelete, Predicate predicate) {
        PersistentManager s = getPersistentManager(classToDelete);
        if(s instanceof DatabaseManager)
        ((DatabaseManager)s).delete(classToDelete, predicate);
    }

    /**
     * Objects created from persistent database. They are however,  not cached anyway. You need
     * to cache them if requires.
     *
     * @param classToFind DOCUMENT ME!
     * @param predicate
     *
     * @return
     */
    
    public static List find(Class classToFind, Predicate predicate) {
        long l = System.currentTimeMillis();

        try {
            PersistentManager s = getPersistentManager(classToFind);
            if(s instanceof DatabaseManager)
               return ((DatabaseManager)s).find(classToFind, predicate);
            else
                return Collections.EMPTY_LIST;
        } finally {
            l = System.currentTimeMillis() - l;

            if (log.isDebugEnabled()) {
                log.debug("Find " + classToFind.getName() + " " + predicate + " " + l);
            }
        }
    }

    public static List find(Class classToFind, String stmt, Predicate predicate) {
        long l = System.currentTimeMillis();

        try {
            PersistentManager s = getPersistentManager(classToFind);
            if(s instanceof DatabaseManager)               
                return ((DatabaseManager)s).find(classToFind, stmt, predicate);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            l = System.currentTimeMillis() - l;

            if (log.isDebugEnabled()) {
                log.debug("Find " + classToFind.getName() + " " + predicate + " " + l);
            }
        }

        return Collections.EMPTY_LIST;
    }

    public static List find(Class classToFind, Predicate predicate, long limit) {
        long l = System.currentTimeMillis();

        try {
            PersistentManager s = getPersistentManager(classToFind);
            
            if(s instanceof DatabaseManager)               
                return ((DatabaseManager)s).find(classToFind, predicate, limit);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            l = System.currentTimeMillis() - l;

            if (log.isDebugEnabled()) {
                log.debug("Find " + classToFind.getName() + " " + predicate + " " + l);
            }
        }

        return Collections.EMPTY_LIST;
    }

    public static ModelBean findById(Class classToFind, String id) {
        if (id == null) {
            return null;
        }

        PersistentManager s = PersistentManagerRegistry.getPersistentManager(classToFind);

        return (ModelBean) s.findById(classToFind, id);
    }

    public static void registerDescriptor(Class pClass, PersistentDescriptor pp) {
        persistentDescriptors.put(pClass, pp);
    }

    public static void registerPersistentManager(Class pClass, PersistentManager pm) {
        persistentManagers.put(pClass, pm);
    }

    public static void update(PersistentContext ctx, Object obj) {
        if (obj instanceof ModelBean) {
            ((ModelBean) obj).update(ctx);
        }
    }
}
